home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src-glu / quadric.c < prev    next >
C/C++ Source or Header  |  1998-12-15  |  22KB  |  855 lines

  1. /* $Id: quadric.c,v 1.16 1998/06/01 01:08:36 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.6
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: quadric.c,v $
  26.  * Revision 1.16  1998/06/01 01:08:36  brianp
  27.  * small update for Next/OpenStep from Alexander Mai
  28.  *
  29.  * Revision 1.15  1998/03/15 18:28:54  brianp
  30.  * reimplemented gluDisk() point and line mode
  31.  *
  32.  * Revision 1.14  1998/03/15 18:14:17  brianp
  33.  * fixed a compiler cast warning
  34.  *
  35.  * Revision 1.13  1998/02/07 14:28:34  brianp
  36.  * another change to gluQuadricCallback(), this time for StormC compiler
  37.  *
  38.  * Revision 1.12  1998/02/05 00:43:19  brianp
  39.  * Yes, still another change to gluQuadricCallback()!
  40.  *
  41.  * Revision 1.11  1998/02/04 00:27:43  brianp
  42.  * yet another change to gluQuadricCallback()!
  43.  *
  44.  * Revision 1.10  1998/02/04 00:23:23  brianp
  45.  * fixed CALLBACK problem in gluQuadricCallback() (Stephane Rehel)
  46.  *
  47.  * Revision 1.9  1998/02/04 00:20:09  brianp
  48.  * added missing (int) in ErrorFunc cast
  49.  *
  50.  * Revision 1.8  1998/01/16 03:37:51  brianp
  51.  * fixed another assignment warning in gluQuadricCallback()
  52.  *
  53.  * Revision 1.7  1998/01/16 03:35:26  brianp
  54.  * fixed Windows compilation warnings (Theodore Jump)
  55.  *
  56.  * Revision 1.6  1997/10/29 02:02:20  brianp
  57.  * various MS Windows compiler changes (David Bucciarelli, v20 3dfx driver)
  58.  *
  59.  * Revision 1.5  1997/09/17 01:51:48  brianp
  60.  * changed glu*Callback() functions to match prototype in glu.h
  61.  *
  62.  * Revision 1.4  1997/07/24 01:28:44  brianp
  63.  * changed precompiled header symbol from PCH to PC_HEADER
  64.  *
  65.  * Revision 1.3  1997/05/28 02:29:38  brianp
  66.  * added support for precompiled headers (PCH), inserted APIENTRY keyword
  67.  *
  68.  * Revision 1.2  1997/03/12 02:15:38  brianp
  69.  * fixed problem in gluPartialDisk() reported by Kenneth H. Carpenter
  70.  *
  71.  * Revision 1.1  1996/09/27 01:19:39  brianp
  72.  * Initial revision
  73.  *
  74.  */
  75.  
  76.  
  77. /* TODO:
  78.  *   texture coordinate support
  79.  *   flip normals according to orientation
  80.  *   there's still some inside/outside orientation bugs in possibly all
  81.  *     but the sphere function
  82.  */
  83.  
  84.  
  85. #ifdef PC_HEADER
  86. #include "all.h"
  87. #else
  88. #include <math.h>
  89. #include <stdio.h>
  90. #include <stdlib.h>
  91. #include "gluP.h"
  92. #endif
  93.  
  94.  
  95.  
  96. #ifndef M_PI
  97. #  define M_PI (3.1415926)
  98. #endif
  99.  
  100.  
  101. /*
  102.  * Convert degrees to radians:
  103.  */
  104. #define DEG_TO_RAD(A)   ((A)*(M_PI/180.0))
  105.  
  106.  
  107. /*
  108.  * Sin and Cos for degree angles:
  109.  */
  110. #define SIND( A )   sin( (A)*(M_PI/180.0) )
  111. #define COSD( A)    cos( (A)*(M_PI/180.0) )
  112.  
  113.  
  114. /*
  115.  * Texture coordinates if texture flag is set
  116.  */
  117. #define TXTR_COORD(x,y)    if (qobj->TextureFlag) glTexCoord2f(x,y);
  118.  
  119.  
  120. #if defined(AMIGA) && defined(__PPC__)
  121. void ErrorFuncPPC(GLenum err);
  122. #endif
  123.  
  124. struct GLUquadricObj {
  125.     GLenum  DrawStyle;              /* GLU_FILL, LINE, SILHOUETTE, or POINT */
  126.     GLenum Orientation;             /* GLU_INSIDE or GLU_OUTSIDE */
  127.     GLboolean TextureFlag;          /* Generate texture coords? */
  128.     GLenum Normals;         /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
  129.     void (CALLBACK *ErrorFunc)(GLenum err); /* Error handler callback function */
  130. #if defined(AMIGA) && defined(__PPC__)
  131.     void (CALLBACK *ErrorFuncPPC)(GLenum err); /* Error handler callback function */
  132. #endif
  133. };
  134.  
  135.  
  136.  
  137. /*
  138.  * Process a GLU error.
  139.  */
  140. static void quadric_error( GLUquadricObj *qobj, GLenum error, const char *msg )
  141. {
  142.    /* Call the error call back function if any */
  143.    if (qobj->ErrorFunc) {
  144. #if defined(AMIGA) && defined(__PPC__)
  145.       currentCallback = (void *)qobj->ErrorFunc;
  146.       (*qobj->ErrorFuncPPC)( error );
  147. #else
  148.       (*qobj->ErrorFunc)( error );
  149. #endif
  150.    }
  151.    /* Print a message to stdout if MESA_DEBUG variable is defined */
  152.    if (getenv("MESA_DEBUG")) {
  153.       fprintf(stderr,"GLUError: %s: %s\n", (char*) gluErrorString(error), msg);
  154.    }
  155. }
  156.  
  157.  
  158.  
  159.  
  160. GLUquadricObj * APIENTRY gluNewQuadric( void )
  161. {
  162.    GLUquadricObj *q;
  163.  
  164.    q = (GLUquadricObj *) malloc( sizeof(struct GLUquadricObj) );
  165.    if (q) {
  166.       q->DrawStyle = GLU_FILL;
  167.       q->Orientation = GLU_OUTSIDE;
  168.       q->TextureFlag = GL_FALSE;
  169.       q->Normals = GLU_SMOOTH;
  170.       q->ErrorFunc = NULL;
  171.    }
  172.    return q;
  173. }
  174.  
  175.  
  176.  
  177. void APIENTRY gluDeleteQuadric( GLUquadricObj *state )
  178. {
  179.    if (state) {
  180.       free( (void *) state );
  181.    }
  182. }
  183.  
  184.  
  185.  
  186. /*
  187.  * Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE,
  188.  * or GLU_POINT.
  189.  */
  190. void APIENTRY gluQuadricDrawStyle( GLUquadricObj *quadObject, GLenum drawStyle )
  191. {
  192.    if (quadObject && (drawStyle==GLU_FILL || drawStyle==GLU_LINE
  193.            || drawStyle==GLU_SILHOUETTE || drawStyle==GLU_POINT)) {
  194.       quadObject->DrawStyle = drawStyle;
  195.    }
  196.    else {
  197.       quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle" );
  198.    }
  199. }
  200.  
  201.  
  202.  
  203. /*
  204.  * Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
  205.  */
  206. void APIENTRY gluQuadricOrientation( GLUquadricObj *quadObject,
  207.                      GLenum orientation )
  208. {
  209.    if (quadObject && (orientation==GLU_INSIDE || orientation==GLU_OUTSIDE)) {
  210.       quadObject->Orientation = orientation;
  211.    }
  212.    else {
  213.       quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation" );
  214.    }
  215. }
  216.  
  217.  
  218.  
  219. /*
  220.  * Set the error handler callback function.
  221.  */
  222. void APIENTRY gluQuadricCallback( GLUquadricObj *qobj,
  223.                   GLenum which, void (CALLBACK *fn)() )
  224. {
  225.    /*
  226.     * UGH, this is a mess!  I thought ANSI was a standard.
  227.     */
  228.    if (qobj && which==GLU_ERROR) {
  229. #ifdef __CYGWIN32__
  230.       qobj->ErrorFunc = (void(*)(int))fn;
  231. #elif defined(OPENSTEP)
  232.       qobj->ErrorFunc = (void(*)(GLenum))fn;
  233. #elif defined(_WIN32)
  234.       qobj->ErrorFunc = (void(CALLBACK*)(int))fn;
  235. #elif defined(__STORM__)
  236.       qobj->ErrorFunc = (void(CALLBACK*)(GLenum))fn;
  237. #if defined(AMIGA) && defined(__PPC__)
  238.       qobj->ErrorFuncPPC = (void(CALLBACK*)(GLenum))ErrorFuncPPC;
  239. #endif
  240. #else
  241.       qobj->ErrorFunc = (void(CALLBACK*)())fn;
  242. #endif
  243.    }
  244. }
  245.  
  246.  
  247. void APIENTRY gluQuadricNormals( GLUquadricObj *quadObject, GLenum normals )
  248. {
  249.    if (quadObject
  250.      && (normals==GLU_NONE || normals==GLU_FLAT || normals==GLU_SMOOTH)) {
  251.       quadObject->Normals = normals;
  252.    }
  253. }
  254.  
  255.  
  256. void APIENTRY gluQuadricTexture( GLUquadricObj *quadObject,
  257.                  GLboolean textureCoords )
  258. {
  259.    if (quadObject) {
  260.       quadObject->TextureFlag = textureCoords;
  261.    }
  262. }
  263.  
  264.  
  265.  
  266.  
  267. /*
  268.  * Call glNormal3f after scaling normal to unit length.
  269.  */
  270. static void normal3f( GLfloat x, GLfloat y, GLfloat z )
  271. {
  272.    GLdouble mag;
  273.  
  274.    mag = sqrt( x*x + y*y + z*z );
  275.    if (mag>0.00001F) {
  276.       x /= mag;
  277.       y /= mag;
  278.       z /= mag;
  279.    }
  280.    glNormal3f( x, y, z );
  281. }
  282.  
  283.  
  284.  
  285. void APIENTRY gluCylinder( GLUquadricObj *qobj,
  286.                GLdouble baseRadius, GLdouble topRadius,
  287.                GLdouble height, GLint slices, GLint stacks )
  288. {
  289.    GLdouble da, r, dr, dz;
  290.    GLfloat x, y, z, nz, nsign;
  291.    GLint i, j;
  292.  
  293.    if (qobj->Orientation==GLU_INSIDE) {
  294.       nsign = -1.0;
  295.    }
  296.    else {
  297.       nsign = 1.0;
  298.    }
  299.  
  300.    da = 2.0*M_PI / slices;
  301.    dr = (topRadius-baseRadius) / stacks;
  302.    dz = height / stacks;
  303.    nz = (baseRadius-topRadius) / height;  /* Z component of normal vectors */
  304.  
  305.    if (qobj->DrawStyle==GLU_POINT) {
  306.       glBegin( GL_POINTS );
  307.       for (i=0;i<slices;i++) {
  308.      x = cos(i*da);
  309.      y = sin(i*da);
  310.      normal3f( x*nsign, y*nsign, nz*nsign );
  311.  
  312.      z = 0.0;
  313.      r = baseRadius;
  314.      for (j=0;j<=stacks;j++) {
  315.         glVertex3f( x*r, y*r, z );
  316.         z += dz;
  317.         r += dr;
  318.      }
  319.       }
  320.       glEnd();
  321.    }
  322.    else if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
  323.       /* Draw rings */
  324.       if (qobj->DrawStyle==GLU_LINE) {
  325.      z = 0.0;
  326.      r = baseRadius;
  327.      for (j=0;j<=stacks;j++) {
  328.         glBegin( GL_LINE_LOOP );
  329.         for (i=0;i<slices;i++) {
  330.            x = cos(i*da);
  331.            y = sin(i*da);
  332.            normal3f( x*nsign, y*nsign, nz*nsign );
  333.            glVertex3f( x*r, y*r, z );
  334.         }
  335.         glEnd();
  336.         z += dz;
  337.         r += dr;
  338.      }
  339.       }
  340.       else {
  341.      /* draw one ring at each end */
  342.      if (baseRadius!=0.0) {
  343.         glBegin( GL_LINE_LOOP );
  344.         for (i=0;i<slices;i++) {
  345.            x = cos(i*da);
  346.            y = sin(i*da);
  347.            normal3f( x*nsign, y*nsign, nz*nsign );
  348.            glVertex3f( x*baseRadius, y*baseRadius, 0.0 );
  349.         }
  350.         glEnd();
  351.         glBegin( GL_LINE_LOOP );
  352.         for (i=0;i<slices;i++) {
  353.            x = cos(i*da);
  354.            y = sin(i*da);
  355.            normal3f( x*nsign, y*nsign, nz*nsign );
  356.            glVertex3f( x*topRadius, y*topRadius, height );
  357.         }
  358.         glEnd();
  359.      }
  360.       }
  361.       /* draw length lines */
  362.       glBegin( GL_LINES );
  363.       for (i=0;i<slices;i++) {
  364.      x = cos(i*da);
  365.      y = sin(i*da);
  366.      normal3f( x*nsign, y*nsign, nz*nsign );
  367.      glVertex3f( x*baseRadius, y*baseRadius, 0.0 );
  368.      glVertex3f( x*topRadius, y*topRadius, height );
  369.       }
  370.       glEnd();
  371.    }
  372.    else if (qobj->DrawStyle==GLU_FILL) {
  373.       GLfloat du = 1.0 / slices;
  374.       GLfloat dv = 1.0 / stacks;
  375.       GLfloat tcx = 0.0, tcy = 0.0;
  376.  
  377.       for (i=0;i<slices;i++) {
  378.      GLfloat x1 = -sin(i*da);
  379.      GLfloat y1 = cos(i*da);
  380.      GLfloat x2 = -sin((i+1)*da);
  381.      GLfloat y2 = cos((i+1)*da);
  382.      z = 0.0;
  383.      r = baseRadius;
  384.      tcy = 0.0;
  385.      glBegin( GL_QUAD_STRIP );
  386.      for (j=0;j<=stacks;j++) {
  387.         if (nsign==1.0) {
  388.            normal3f( x1*nsign, y1*nsign, nz*nsign );
  389.            TXTR_COORD(tcx, tcy);
  390.            glVertex3f( x1*r, y1*r, z );
  391.            normal3f( x2*nsign, y2*nsign, nz*nsign );
  392.            TXTR_COORD(tcx+du, tcy);
  393.            glVertex3f( x2*r, y2*r, z );
  394.         }
  395.         else {
  396.            normal3f( x2*nsign, y2*nsign, nz*nsign );
  397.            TXTR_COORD(tcx, tcy);
  398.            glVertex3f( x2*r, y2*r, z );
  399.            normal3f( x1*nsign, y1*nsign, nz*nsign );
  400.            TXTR_COORD(tcx+du, tcy);
  401.            glVertex3f( x1*r, y1*r, z );
  402.         }
  403.         z += dz;
  404.         r += dr;
  405.         tcy += dv;
  406.      }
  407.      glEnd();
  408.      tcx += du;
  409.       }
  410.    }
  411. }
  412.  
  413.  
  414.  
  415.  
  416.  
  417. void APIENTRY gluSphere( GLUquadricObj *qobj,
  418.              GLdouble radius, GLint slices, GLint stacks )
  419. {
  420.    GLfloat rho, drho, theta, dtheta;
  421.    GLfloat x, y, z;
  422.    GLfloat s, t, ds, dt;
  423.    GLint i, j, imin, imax;
  424.    GLboolean normals;
  425.    GLfloat nsign;
  426.  
  427.    if (qobj->Normals==GLU_NONE) {
  428.       normals = GL_FALSE;
  429.    }
  430.    else {
  431.       normals = GL_TRUE;
  432.    }
  433.    if (qobj->Orientation==GLU_INSIDE) {
  434.       nsign = -1.0;
  435.    }
  436.    else {
  437.       nsign = 1.0;
  438.    }
  439.  
  440.    drho = M_PI / (GLfloat) stacks;
  441.    dtheta = 2.0 * M_PI / (GLfloat) slices;
  442.  
  443.    /* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis */
  444.    /* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */
  445.    /* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */
  446.  
  447.    if (qobj->DrawStyle==GLU_FILL) {
  448.      if (!qobj->TextureFlag) {
  449.       /* draw +Z end as a triangle fan */
  450.       glBegin( GL_TRIANGLE_FAN );
  451.       glNormal3f( 0.0, 0.0, 1.0 );
  452.       TXTR_COORD(0.5,1.0);
  453.       glVertex3f( 0.0, 0.0, nsign * radius );
  454.       for (j=0;j<=slices;j++) {
  455.      theta = (j==slices) ? 0.0 : j * dtheta;
  456.      x = -sin(theta) * sin(drho);
  457.      y = cos(theta) * sin(drho);
  458.      z = nsign * cos(drho);
  459.      if (normals)  glNormal3f( x*nsign, y*nsign, z*nsign );
  460.      glVertex3f( x*radius, y*radius, z*radius );
  461.       }
  462.       glEnd();
  463.      }
  464.  
  465.       ds = 1.0 / slices;
  466.       dt = 1.0 / stacks;
  467.       t = 1.0;  /* because loop now runs from 0 */
  468.       if (qobj->TextureFlag) {
  469.     imin = 0;
  470.     imax = stacks;
  471.       }
  472.       else {
  473.     imin = 1;
  474.     imax = stacks-1;
  475.       }
  476.  
  477.       /* draw intermediate stacks as quad strips */
  478.       for (i=imin;i<imax;i++) {
  479.      rho = i * drho;
  480.      glBegin( GL_QUAD_STRIP );
  481.      s = 0.0;
  482.      for (j=0;j<=slices;j++) {
  483.         theta = (j==slices) ? 0.0 : j * dtheta;
  484.         x = -sin(theta) * sin(rho);
  485.         y = cos(theta) * sin(rho);
  486.         z = nsign * cos(rho);
  487.         if (normals)  glNormal3f( x*nsign, y*nsign, z*nsign );
  488.         TXTR_COORD(s,t);
  489.         glVertex3f( x*radius, y*radius, z*radius );
  490.         x = -sin(theta) * sin(rho+drho);
  491.         y = cos(theta) * sin(rho+drho);
  492.         z = nsign * cos(rho+drho);
  493.         if (normals)  glNormal3f( x*nsign, y*nsign, z*nsign );
  494.         TXTR_COORD(s,t-dt);
  495.         s += ds;
  496.         glVertex3f( x*radius, y*radius, z*radius );
  497.      }
  498.      glEnd();
  499.      t -= dt;
  500.       }
  501.  
  502.      if (!qobj->TextureFlag) {
  503.       /* draw -Z end as a triangle fan */
  504.       glBegin( GL_TRIANGLE_FAN );
  505.       glNormal3f( 0.0, 0.0, -1.0 );
  506.       TXTR_COORD(0.5,0.0);
  507.       glVertex3f( 0.0, 0.0, -radius*nsign );
  508.       rho = M_PI - drho;
  509.       s = 1.0;
  510.       t = dt;
  511.       for (j=slices;j>=0;j--) {
  512.      theta = (j==slices) ? 0.0 : j * dtheta;
  513.      x = -sin(theta) * sin(rho);
  514.      y = cos(theta) * sin(rho);
  515.      z = nsign * cos(rho);
  516.      if (normals)  glNormal3f( x*nsign, y*nsign, z*nsign );
  517.      TXTR_COORD(s,t);
  518.      s -= ds;
  519.      glVertex3f( x*radius, y*radius, z*radius );
  520.       }
  521.       glEnd();
  522.      }
  523.    }
  524.    else if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
  525.       /* draw stack lines */
  526.       for (i=1;i<stacks;i++) {  /* stack line at i==stacks-1 was missing here */
  527.      rho = i * drho;
  528.      glBegin( GL_LINE_LOOP );
  529.      for (j=0;j<slices;j++) {
  530.         theta = j * dtheta;
  531.         x = cos(theta) * sin(rho);
  532.         y = sin(theta) * sin(rho);
  533.         z = cos(rho);
  534.         if (normals)  glNormal3f( x*nsign, y*nsign, z*nsign );
  535.         glVertex3f( x*radius, y*radius, z*radius );
  536.      }
  537.      glEnd();
  538.       }
  539.       /* draw slice lines */
  540.       for (j=0;j<slices;j++) {
  541.      theta = j * dtheta;
  542.      glBegin( GL_LINE_STRIP );
  543.      for (i=0;i<=stacks;i++) {
  544.         rho = i * drho;
  545.         x = cos(theta) * sin(rho);
  546.         y = sin(theta) * sin(rho);
  547.         z = cos(rho);
  548.         if (normals)  glNormal3f( x*nsign, y*nsign, z*nsign );
  549.         glVertex3f( x*radius, y*radius, z*radius );
  550.      }
  551.      glEnd();
  552.       }
  553.    }
  554.    else if (qobj->DrawStyle==GLU_POINT) {
  555.       /* top and bottom-most points */
  556.       glBegin( GL_POINTS );
  557.       if (normals)  glNormal3f( 0.0, 0.0, nsign );
  558.       glVertex3d( 0.0, 0.0, radius );
  559.       if (normals)  glNormal3f( 0.0, 0.0, -nsign );
  560.       glVertex3d( 0.0, 0.0, -radius );
  561.  
  562.       /* loop over stacks */
  563.       for (i=1;i<stacks-1;i++) {
  564.      rho = i * drho;
  565.      for (j=0;j<slices;j++) {
  566.         theta = j * dtheta;
  567.         x = cos(theta) * sin(rho);
  568.         y = sin(theta) * sin(rho);
  569.         z = cos(rho);
  570.         if (normals)  glNormal3f( x*nsign, y*nsign, z*nsign );
  571.         glVertex3f( x*radius, y*radius, z*radius );
  572.      }
  573.       }
  574.       glEnd();
  575.    }
  576.  
  577. }
  578.  
  579.  
  580.  
  581. void APIENTRY gluDisk( GLUquadricObj *qobj,
  582.                GLdouble innerRadius, GLdouble outerRadius,
  583.                GLint slices, GLint loops )
  584. {
  585.    GLfloat da, dr;
  586. #if 0
  587.    GLdouble a, da;
  588.    GLfloat r, dr;
  589.    GLfloat x, y;
  590.    GLfloat r1, r2, dtc;
  591.    GLint s, l;
  592. #endif
  593.  
  594.    /* Normal vectors */
  595.    if (qobj->Normals!=GLU_NONE) {
  596.       if (qobj->Orientation==GLU_OUTSIDE) {
  597.      glNormal3f( 0.0, 0.0, +1.0 );
  598.       }
  599.       else {
  600.      glNormal3f( 0.0, 0.0, -1.0 );
  601.       }
  602.    }
  603.  
  604.    da = 2.0*M_PI / slices;
  605.    dr = (outerRadius-innerRadius) / (GLfloat) loops;
  606.  
  607.    switch (qobj->DrawStyle) {
  608.       case GLU_FILL:
  609.       {
  610.      /* texture of a gluDisk is a cut out of the texture unit square
  611.       * x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
  612.       * (linear mapping)
  613.       */
  614.      GLfloat dtc = 2.0f * outerRadius;
  615.      GLfloat sa,ca;
  616.      GLfloat r1 = innerRadius;
  617.      GLint l;
  618.      for (l=0; l<loops; l++) {
  619.         GLfloat r2 = r1 + dr;
  620.         if (qobj->Orientation==GLU_OUTSIDE) {
  621.            GLint s;
  622.            glBegin( GL_QUAD_STRIP );
  623.            for (s=0;s<=slices;s++) {
  624.           GLfloat a;
  625.           if (s==slices) a = 0.0;
  626.           else  a = s * da;
  627.           sa = sin(a); ca = cos(a);
  628.           TXTR_COORD(0.5+sa*r2/dtc,0.5+ca*r2/dtc);
  629.           glVertex2f( r2*sa, r2*ca );
  630.           TXTR_COORD(0.5+sa*r1/dtc,0.5+ca*r1/dtc);
  631.           glVertex2f( r1*sa, r1*ca );
  632.            }
  633.            glEnd();
  634.         }
  635.         else {
  636.            GLint s;
  637.            glBegin( GL_QUAD_STRIP );
  638.            for (s=slices;s>=0;s--) {
  639.           GLfloat a;
  640.           if (s==slices) a = 0.0;
  641.           else  a = s * da;
  642.           sa = sin(a); ca = cos(a);
  643.           TXTR_COORD(0.5-sa*r2/dtc,0.5+ca*r2/dtc);
  644.           glVertex2f( r2*sa, r2*ca );
  645.           TXTR_COORD(0.5-sa*r1/dtc,0.5+ca*r1/dtc);
  646.           glVertex2f( r1*sa, r1*ca );
  647.            }
  648.            glEnd();
  649.         }
  650.         r1 = r2;
  651.      }
  652.      break;
  653.       }
  654.       case GLU_LINE:
  655.       {
  656.      GLint l, s;
  657.      /* draw loops */
  658.      for (l=0; l<=loops; l++) {
  659.         GLfloat r = innerRadius + l * dr;
  660.         glBegin( GL_LINE_LOOP );
  661.         for (s=0; s<slices; s++) {
  662.            GLfloat a = s * da;
  663.            glVertex2f( r*sin(a), r*cos(a) );
  664.         }
  665.         glEnd();
  666.      }
  667.      /* draw spokes */
  668.      for (s=0; s<slices; s++) {
  669.         GLfloat a = s * da;
  670.         GLfloat x = sin(a);
  671.         GLfloat y = cos(a);
  672.         glBegin( GL_LINE_STRIP );
  673.         for (l=0; l<=loops; l++) {
  674.            GLfloat r = innerRadius + l * dr;
  675.            glVertex2f( r*x, r*y );
  676.         }
  677.         glEnd();
  678.      }
  679.      break;
  680.       }
  681.       case GLU_POINT:
  682.       {
  683.      GLint s;
  684.      glBegin( GL_POINTS );
  685.      for (s=0; s<slices; s++) {
  686.         GLfloat a = s * da;
  687.         GLfloat x = sin(a);
  688.         GLfloat y = cos(a);
  689.         GLint l;
  690.         for (l=0; l<=loops; l++) {
  691.            GLfloat r = innerRadius * l * dr;
  692.            glVertex2f( r*x, r*y );
  693.         }
  694.      }
  695.      glEnd();
  696.      break;
  697.       }
  698.       case GLU_SILHOUETTE:
  699.       {
  700.      if (innerRadius!=0.0) {
  701.         GLfloat a;
  702.         glBegin( GL_LINE_LOOP );
  703.         for (a=0.0; a<2.0*M_PI; a+=da) {
  704.            GLfloat x = innerRadius * sin(a);
  705.            GLfloat y = innerRadius * cos(a);
  706.            glVertex2f( x, y );
  707.         }
  708.         glEnd();
  709.      }
  710.      {
  711.         GLfloat a;
  712.         glBegin( GL_LINE_LOOP );
  713.         for (a=0; a<2.0*M_PI; a+=da) {
  714.            GLfloat x = outerRadius * sin(a);
  715.            GLfloat y = outerRadius * cos(a);
  716.            glVertex2f( x, y );
  717.         }
  718.         glEnd();
  719.      }
  720.      break;
  721.       }
  722.       default:
  723.      abort();
  724.    }
  725. }
  726.  
  727.  
  728.  
  729. void APIENTRY gluPartialDisk( GLUquadricObj *qobj, GLdouble innerRadius,
  730.                   GLdouble outerRadius, GLint slices, GLint loops,
  731.                   GLdouble startAngle, GLdouble sweepAngle )
  732. {
  733.    if (qobj->Normals!=GLU_NONE) {
  734.       if (qobj->Orientation==GLU_OUTSIDE) {
  735.      glNormal3f( 0.0, 0.0, +1.0 );
  736.       }
  737.       else {
  738.      glNormal3f( 0.0, 0.0, -1.0 );
  739.       }
  740.    }
  741.  
  742.    if (qobj->DrawStyle==GLU_POINT) {
  743.       GLint loop, slice;
  744.       GLdouble radius, delta_radius;
  745.       GLdouble angle, delta_angle;
  746.       delta_radius = (outerRadius - innerRadius) / (loops-1);
  747.       delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1));
  748.       glBegin( GL_POINTS );
  749.       radius = innerRadius;
  750.       for (loop=0; loop<loops; loop++) {
  751.      angle = DEG_TO_RAD(startAngle);
  752.      for (slice=0; slice<slices; slice++) {
  753.         glVertex2d( radius * sin(angle), radius * cos(angle) );
  754.         angle += delta_angle;
  755.      }
  756.      radius += delta_radius;
  757.       }
  758.       glEnd();
  759.    }
  760.    else if (qobj->DrawStyle==GLU_LINE) {
  761.       GLint loop, slice;
  762.       GLdouble radius, delta_radius;
  763.       GLdouble angle, delta_angle;
  764.       delta_radius = (outerRadius - innerRadius) / loops;
  765.       delta_angle = DEG_TO_RAD(sweepAngle / slices);
  766.       /* draw rings */
  767.       radius = innerRadius;
  768.       for (loop=0; loop<loops; loop++) {
  769.      angle = DEG_TO_RAD(startAngle);
  770.      glBegin( GL_LINE_STRIP );
  771.      for (slice=0; slice<slices; slice++) {
  772.         glVertex2d( radius * sin(angle), radius * cos(angle) );
  773.         angle += delta_angle;
  774.      }
  775.      glEnd();
  776.      radius += delta_radius;
  777.       }
  778.       /* draw spokes */
  779.       angle = DEG_TO_RAD(startAngle);
  780.       for (slice=0; slice<slices; slice++) {
  781.      radius = innerRadius;
  782.      glBegin( GL_LINE_STRIP );
  783.      for (loop=0; loop<loops; loop++) {
  784.         glVertex2d( radius * sin(angle), radius * cos(angle) );
  785.         radius += delta_radius;
  786.      }
  787.      glEnd();
  788.      angle += delta_angle;
  789.       }
  790.    }
  791.    else if (qobj->DrawStyle==GLU_SILHOUETTE) {
  792.       GLint slice;
  793.       GLdouble angle, delta_angle;
  794.       delta_angle = DEG_TO_RAD(sweepAngle / slices);
  795.       /* draw outer ring */
  796.       glBegin( GL_LINE_STRIP );
  797.       angle = DEG_TO_RAD(startAngle);
  798.       for (slice=0; slice<=slices; slice++) {
  799.      glVertex2d( outerRadius * sin(angle), outerRadius * cos(angle) );
  800.      angle += delta_angle;
  801.       }
  802.       glEnd();
  803.       /* draw inner ring */
  804.       if (innerRadius>0.0) {
  805.      glBegin( GL_LINE_STRIP );
  806.      angle = DEG_TO_RAD(startAngle);
  807.      for (slice=0; slice<slices; slice++) {
  808.         glVertex2d( innerRadius * sin(angle), innerRadius * cos(angle) );
  809.         angle += delta_angle;
  810.      }
  811.      glEnd();
  812.       }
  813.       /* draw spokes */
  814.       if (sweepAngle<360.0) {
  815.      GLdouble stopAngle = startAngle + sweepAngle;
  816.      glBegin( GL_LINES );
  817.      glVertex2d( innerRadius*SIND(startAngle), innerRadius*COSD(startAngle) );
  818.      glVertex2d( outerRadius*SIND(startAngle), outerRadius*COSD(startAngle) );
  819.      glVertex2d( innerRadius*SIND(stopAngle), innerRadius*COSD(stopAngle) );
  820.      glVertex2d( outerRadius*SIND(stopAngle), outerRadius*COSD(stopAngle) );
  821.      glEnd();
  822.       }
  823.    }
  824.    else if (qobj->DrawStyle==GLU_FILL) {
  825.       GLint loop, slice;
  826.       GLdouble radius, delta_radius;
  827.       GLdouble angle, delta_angle;
  828.       delta_radius = (outerRadius - innerRadius) / loops;
  829.       delta_angle = DEG_TO_RAD(sweepAngle / slices);
  830.       radius = innerRadius;
  831.       for (loop=0; loop<loops; loop++) {
  832.      glBegin( GL_QUAD_STRIP );
  833.      angle = DEG_TO_RAD(startAngle);
  834.      for (slice=0; slice<slices; slice++) {
  835.         if (qobj->Orientation==GLU_OUTSIDE) {
  836.            glVertex2d( (radius+delta_radius)*sin(angle),
  837.                (radius+delta_radius)*cos(angle) );
  838.            glVertex2d( radius * sin(angle), radius * cos(angle) );
  839.         }
  840.         else {
  841.            glVertex2d( radius * sin(angle), radius * cos(angle) );
  842.            glVertex2d( (radius+delta_radius)*sin(angle),
  843.                (radius+delta_radius)*cos(angle) );
  844.         }
  845.         angle += delta_angle;
  846.      }
  847.      glEnd();
  848.      radius += delta_radius;
  849.       }
  850.    }
  851. }
  852.  
  853.  
  854.  
  855.